#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<time.h>

#define width 1000
#define high 800

enum balls { red, blue, green, yellow, magenta };//定义颜色为红 蓝 绿 黄 紫

typedef struct ball 
{
	balls one;
	struct ball* behind;
	struct ball* next;
}ball;

ball* head, * list, * p, * o = NULL;
int all[2001][2];//小球可能出现的位置
int speed = -1, count = 0, x = 0, y = 0;//计数用和辅助线用
int z[2];//发射区用  记录小球颜色

void begin();//计算轨迹
void end();//结束
void fail();//游戏失败
void start();//初始化
void show();//界面显示
void showball();//显示球
void update();//更新
void updateuser();//与用户有关的更新

int main()
{
	start();
	begin();
	while (1) {
		show();
	}
	end();

	return 0;
}

void begin()
{
	//轨迹计算
	count = 0;//0被废弃
	while (++count <= 1000)
    {
		all[count][0] = count;
		all[count][1] = 100;
	}
	while (++count <= 1900) 
    {
		all[count][0] = 2000 - count;
		all[count][1] = 700;
	}
	count = 1;
}

void end()
{
	EndBatchDraw();
	closegraph();
}

void fail()
{
	if (count > 1800)
		while (1) 
        {
			settextstyle(50, 0, _T("黑体"));
			outtextxy(375, 375, _T(" you fail "));
		}
}

void start()
{
	int i = 50;
	initgraph(width, high);
	BeginBatchDraw();
	setbkcolor(DARKGRAY);//背景为深灰色
	srand((unsigned int)time(NULL));
	//初始化50个球的属性
	list = head;
	head = (ball*)malloc(sizeof(ball));
	if (head == NULL)
		exit(0);
	head->one = (balls)(rand() % 5);
	list = head;
	list->behind = NULL;
	while (--i) {
		list->next = (ball*)malloc(sizeof(ball));
		if (list->next == NULL)
			exit(0);
		list->next->behind = list;
		list = list->next;
		list->one = (balls)(rand() % 5);
		list->next = NULL;
	}
	//发射区颜色初始化
	z[0] = (balls)(rand() % 5);
	z[1] = (balls)(rand() % 5);
}

void show()
{
	cleardevice();
	//画出小球轨迹
	setlinecolor(LIGHTCYAN);//小球轨迹为亮青色
	setlinestyle(PS_ENDCAP_FLAT, 3);
	line(0, 100, 1000, 100);
	line(200, 700, 1000, 700);
	//辅助线
	setlinestyle(PS_DOT | PS_ENDCAP_FLAT, 1);
	line(x, y, 500, 400);
	//终点
	setcolor(BROWN);//棕
	setfillcolor(BLACK);//黑
	fillcircle(150, 700, 50);
	setcolor(LIGHTGRAY);//白
	setlinestyle(PS_DOT | PS_ENDCAP_FLAT, 1);
	circle(150, 700, 40);
	circle(150, 700, 30);
	circle(150, 700, 20);
	circle(150, 700, 10);
	//发射区
	setfillcolor(LIGHTGRAY);//浅灰
	solidcircle(500, 400, 100);
	switch (z[0]) {
	case red:setfillcolor(RED); break;
	case blue:setfillcolor(BLUE); break;
	case green:setfillcolor(GREEN); break;
	case yellow:setfillcolor(YELLOW); break;
	case magenta:setfillcolor(MAGENTA); break;
	}
	solidcircle(500, 400, 15);
	switch (z[1]) {
	case red:setfillcolor(RED); break;
	case blue:setfillcolor(BLUE); break;
	case green:setfillcolor(GREEN); break;
	case yellow:setfillcolor(YELLOW); break;
	case magenta:setfillcolor(MAGENTA); break;
	}
	solidcircle(500, 450, 15);
	//移动的小球
	showball();
	update();
	updateuser();
	FlushBatchDraw();
}

void showball()
{
	int number = 0;
	list = head;
	while (list != NULL && count - number * 40 > 0) 
    {
		switch (list->one) 
        {
		case red:setfillcolor(RED); break;
		case blue:setfillcolor(BLUE); break;
		case green:setfillcolor(GREEN); break;
		case yellow:setfillcolor(YELLOW); break;
		case magenta:setfillcolor(MAGENTA); break;
		}
		solidcircle(all[count - number * 40][0], all[count - number * 40][1], 15);
		list = list->next;
		number++;
	}
}

void update()
{
	balls judge;
	int number = 1;
	ball* zuo, * you;
	if (speed == -1)
		count++;
	else 
    {
		if (speed >= 3) 
        {
			count++;
			speed = 0;
		}
		else
			speed++;
	}
	if (count > 600 && speed == -1)
		speed = 0;
	fail();
	if (o != NULL) 
    {
		judge = o->one;
		zuo = o;
		you = o;
		//计算个数
		while (you->next->one == judge) 
        {
			number++;
			you = you->next;
		}
		while (zuo->behind->one == judge) 
        {
			number++;
			zuo = zuo->behind;
		}
		//超过3个消除
		if (number >= 3) 
        {
			you->next->behind = zuo->behind;
			zuo->behind->next = you->next;
			while (zuo != you) 
            {
				o = zuo->next;
				free(zuo);
				zuo = o;
			}
			count -= number * 40;
		}
		o = NULL;
	}
}

void updateuser()
{
	MOUSEMSG hit;
	int u, i;
	if (MouseHit()) {
		hit = GetMouseMsg();
		if (hit.uMsg == WM_MOUSEMOVE) 
        {
			x = hit.x;
			y = hit.y;
		}
		if (hit.uMsg == WM_LBUTTONDOWN) 
        {
			u = 0;
			list = head;
			if (count <= 1000 && hit.y < 400) 
            {
				while (list != NULL && count - u * 40 > 0) 
                {
					if (u == 0 && all[count][0] * (400 - hit.y) < 500 * (400 - hit.y) - 300 * (500 - hit.x))
						break;//打空了
					else if (all[count - u * 40][0] * (400 - hit.y) < 500 * (400 - hit.y) - 300 * (500 - hit.x))
						if (all[count - u * 40 + 40][0] * (400 - hit.y) > 500 * (400 - hit.y) - 300 * (500 - hit.x))
							break;//打到上串某两个球的中间
					u++;
				}
			}
			else if (count > 1000) 
            {
				while (list != NULL && count - u * 40 > 0) 
                {
					if (count - u * 40 <= 1000 && hit.y < 400) 
                    {
						if (u == 0 && all[count][0] * (400 - hit.y) < 500 * (400 - hit.y) - 300 * (500 - hit.x))
							break;//打空了
						else if (all[count - u * 40][0] * (400 - hit.y) <= 500 * (400 - hit.y) - 300 * (500 - hit.x) && u != 0)
							if (all[count - u * 40 + 40][0] * (400 - hit.y) >= 500 * (400 - hit.y) - 300 * (500 - hit.x))
								break;//打到上串某两个球的中间
					}
					else if (count - u * 40 > 1000 && hit.y > 400) 
                    {
						if (u == 0 && all[count][0] * (400 - hit.y) < 500 * (400 - hit.y) + 300 * (500 - hit.x))
							break;//打空了
						else if (all[count - u * 40][0] * (400 - hit.y) <= 500 * (400 - hit.y) + 300 * (500 - hit.x) && u != 0)
							if (all[count - u * 40 + 40][0] * (400 - hit.y) >= 500 * (400 - hit.y) + 300 * (500 - hit.x))
								break;//打到下串某两个球的中间
					}
					u++;
				}
			}
			if (u > 0) 
            {
				list = head;
				while (--u) 
                {//搜索插入的位置
					list = list->next;
				}
				p = list->next;
				o = (ball*)malloc(sizeof(ball));
				if (o == NULL)
					exit(0);
				o->one = (balls)z[0];
				z[0] = z[1];
				z[1] = (balls)(rand() % 5);
				list->next = o;//进行插入
				o->behind = list;
				o->next = p;
				p->behind = o;
				count += 40;
			}
		}
		//右键换球
		if (hit.uMsg == WM_RBUTTONDOWN) 
        {
			u = z[0];
			z[0] = z[1];
			z[1] = u;
		}
	}
}